在用java开发桌面应用程序时(虽然现在很少有人用),如果将项目导出成jar包而项目中包含图片等资源时,可能会无法正确加载这些资源。这主要是因为jar包是一个单独的文件而非文件夹,绝对不可能通过 “file:/e:/…/ResourceJar.jar/resource/123.jpg” 这种形式的文件URL来定位 123.jpg 。所以即使是相对路径,也无法定位到jar文件内的图片资源。解决方法有如下两种。
将图片资源分离出来(不打包)
如果你的项目结构图是这样的: 而代码是这样写的:
package com.xiaoli.tank;
import java.awt.Graphics;
import java.awt.Rectangle;
import javax.swing.ImageIcon;
public class River {
int x,y;
ImageIcon river = new ImageIcon("images/river.gif");
public River(int x,int y){
this.x=x;
this.y=y;
}
public void draw(Graphics g){
g.drawImage(river.getImage(),x, y,null);
}
public Rectangle getRect() {
return new Rectangle(x, y,river.getIconWidth(),river.getIconHeight());
}
}
那么将项目打包后的jar文件和images文件放在同一目录下即可,如图所示: ![456](https://img-blog.csdn.net/2018043023152841?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3RyYW5zZm9ybWVyX1dTWg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
整体打包
很多时候放置两个文件很变扭,那么我们可以将整个项目进行打包。在项目的 src 目录下新建 package images ,将图片资源放入 images 包下,如下图所示: 这时候对应的代码应该写为:
package com.xiaoli.tank;
import java.awt.Graphics;
import java.awt.Rectangle;
import javax.swing.ImageIcon;
public class River {
int x,y;
ImageIcon river = new ImageIcon(this.getClass().getClassLoader().getResource("images/river.gif"));
public River(int x,int y){
this.x=x;
this.y=y;
}
public void draw(Graphics g){
g.drawImage(river.getImage(),x, y,null);
}
public Rectangle getRect() {
return new Rectangle(x, y,river.getIconWidth(),river.getIconHeight());
}
}
ClassLoader 是类加载器的抽象类。它可以在运行时动态的获取加载类的运行信息。可以这样说,当我们调用jar包中的 River 类时,JVM加载进 River 类,并记录下 River 运行时信息(包括 River 所在jar包的路径信息)。而 ClassLoader 类中的方法可以帮助我们动态的获取这些信息: ● public URL getResource(String name); 查找具有给定名称的资源。资源是可以通过类代码以与代码基无关的方式访问的一些数据(图像、声音、文本等)。并返回资源的URL对象。 ● public InputStream getResourceAsStream(String name); 返回读取指定资源的输入流。这个方法很重要,可以直接获得jar包中文件的内容。ClassLoader 是 abstract 的,不可能实例化对象,更加不可能通过 ClassLoader 调用上面两个方法。所以我们真正写代码的时候,是通过 Class 类中的 getResource() 和 getResourceAsStream() 方法,这两个方法会委托 ClassLoader 中的 getResource() 和 getResourceAsStream() 方法。
参考自:http://blog.51cto.com/cjcxd2004/1256381
|